#include "client.h"
#include "clientFuncs.h"
#define PORT 8080

int getCommand(char *commandStr, char *cmd)
{
    memcpy(cmd, "cd", 2);
    return 1;
}
int main()
{
    // 用户名和密码输入
    char username[255] = {0};
    char password[255] = {0};
    printf("请输入用户名:");
    scanf("%s", username);
    printf("请输入密码:");
    scanf("%s", password);

    // 网络连接
    int socketFd;
    int ret = netLink(&socketFd);
    if (ret == -1)
    {
        printf("网络连接失败...\n");
        exit(-1); // 返回-1表示连接失败
    }

    // 用户登录
    ret = userLogin(socketFd, username, password);
    if (ret == -1)
    {
        printf("登录失败...\n");
        exit(-1); // 返回-1表示登录失败
    }

    // 初始化客户端结构体，包括当前路径、状态、用户名
    clientInfo_st clientInfo;
    memset(&clientInfo, 0, sizeof(clientInfo));
    initClientInfo(username, &clientInfo);

    // 与服务端进行交互
    char commandStr[255]; // 这个保存用户输入的整个字符串
    char cmd[20];         // 这个保存用户输入的命令，即如果输入mkdir cpp，拿到mkdir
    char recvBuf[1024] = {0};
    int alreadDataLen = 0; // 对于发送数据，前面拼接字符串的偏移量
    while (1)
    {
        memset(commandStr, 0, sizeof(commandStr));
        printf("请输入命令:");
        fflush(stdout);
        // 这个count会将最后的回车键也算上大小，比如你输入mkdir，count大小为6，strlen也是一样的
        int count = read(STDIN_FILENO, commandStr, sizeof(commandStr));
        if (count == 1 && strcmp(commandStr, "\n") == 0)
            continue;
        // if(strcmp(commandStr, "exit") == 0 || strcmp(commandStr, "Exit"))
        // {
        //     printf("退出...\n");
        //     close(socketFd); exit(-1);
        // }

        // 去掉回车键
        commandStr[count - 1] = '\0';
        // 去掉字符串前后的空格
        trimString(commandStr);
        // int ret = getCommand(commandStr, cmd);
        CMD_TYPE cmdType = getCommandType(commandStr, cmd);
        // int tmp;
        // if(strcmp(splitString(commandStr," ",&tmp)[0],"rm") == 0)
        // cmdType = REMOVE;
        if (cmdType == CD)
        {
            // if cd / 则在这里直接处理了
            int tokenSize;
            char **tokens4 = splitString(commandStr, " ", &tokenSize);
            if (strcmp(tokens4[1], "/") == 0)
            {
                memset(clientInfo.curPath, 0, sizeof(clientInfo.curPath));
                clientInfo.curPath[0] = '/';
                continue;;
            }
            
            /*
                需要什么数据自己定，函数名和参数自己定，我建议 【命令PackageData】
                我能提供：用户名，客户端当期路径，客户端发送的命令，比如mkdir cpp
                TODO:
                lsPackageData()
            */
            // char additionals[255] = "key:filesize,value:1234&key:username,value:tk";
            send_command(socketFd, commandStr, clientInfo.uname, clientInfo.curPath, NULL);
            // 接收返回的数据
            // printf("等待返回的数据..\n");
            // int count = recv(sockFd, recvBuf, sizeof(recvBuf), 0);
            // if (count == 0)
            // {
            //     printf("服务端关闭，退出...\n");
            //     exit(1);
            // }
            // 处理返回来的数据
            handCdReturnData(socketFd, &clientInfo, commandStr);
        }
        else if (cmdType == LS)
        {
            // printf("----------客户端开始ls命令处理----------...\n");
            send_command(socketFd, commandStr, clientInfo.uname, clientInfo.curPath, NULL);
            memset(recvBuf, 0, sizeof(recvBuf));
            int dataLen;
            int count = recv(socketFd, &dataLen, 4, MSG_WAITALL);
            if (dataLen == 0)
            {
                printf("此目录没有文件或文件夹...\n");
                continue;
            }
            if (count == 0)
                exit(-1);
            count = recv(socketFd, recvBuf, dataLen, MSG_WAITALL);
            if (count == 0)
                exit(-1); // 服务器关闭
            int tokenSize;
            char **token = splitString(recvBuf, "&", &tokenSize);
            for (size_t i = 0; i < tokenSize; i++)
            {
                printf("%s  ", token[i]);
            }
            if (tokenSize == 0)
                printf("此目录没有文件...");
            printf("\n");
            continue;
        }
        else if (cmdType == PUTS)
        {
            // 检查文件是否存在...
            int tokenSize;
            char **tokens = splitString(commandStr, " /", &tokenSize);
            int r_fd = open(tokens[1], O_RDONLY);
            if (r_fd == -1)
            {
                close(r_fd);
                printf("没有%s文件存在...\n", tokens[1]);
                continue;
            }
            close(r_fd);
            /*
                需要什么数据自己定，函数名和参数自己定，我建议 【命令PackageData】
                我能提供：用户名，客户端当期路径，客户端发送的命令，比如mkdir cpp
                TODO:
                lsPackageData()
            */
            send_command(socketFd, commandStr, clientInfo.uname, clientInfo.curPath, NULL);
            // 接收返回的数据
            // int count = recv(sockFd, recvBuf, sizeof(recvBuf), 0);
            // if (count == 0)
            // {
            //     printf("服务端关闭，退出...\n");
            //     exit(1);
            // }
            // 处理返回来的数据
            // int ret = handCdReturnData(char* recvBuf);
            handPutsReturnData(socketFd, commandStr);
        }
        else if (cmdType == GETS)
        {
            cHandleGets(socketFd, commandStr, clientInfo.uname, clientInfo.curPath);
        }
        else if (cmdType == REMOVE /*|| cmdType == RM*/)
        {
            /*
                需要什么数据自己定，函数名和参数自己定，我建议 【命令PackageData】
                我能提供：用户名，客户端当期路径，客户端发送的命令，比如mkdir cpp
            */
            send_command(socketFd, commandStr, clientInfo.uname, clientInfo.curPath, NULL);
            // 接收返回的数据
            memset(recvBuf, 0, sizeof(recvBuf));
            int count = recv(socketFd, recvBuf, sizeof(recvBuf), 0);
            if (count == 0)
            {
                printf("服务端关闭，退出...\n");
                exit(1);
            }
            // 处理返回来的数据
            // 解析前4个字节
            int status;
            memcpy(&status, recvBuf, 4);
            if (status == 0)
            {
                printf("删除失败...没有该文件或者权限不足...\n");
            }
            else
            {
                printf("删除成功...\n");
            }
            continue;
        }
        else if (cmdType == PWD)
        {
            // 得到当前的工作路径
            printf("当前路径为:%s\n", clientInfo.curPath);
            continue;
        }
        else if (cmdType == MKDIR)
        {
            /*
                需要什么数据自己定，函数名和参数自己定，我建议 【命令PackageData】
                我能提供：用户名，客户端当期路径，客户端发送的命令，比如mkdir cpp
                TODO:
                lsPackageData()
            */
            send_command(socketFd, commandStr, clientInfo.uname, clientInfo.curPath, NULL);
            // // 接收返回的数据
            // int count = recv(sockFd, recvBuf, sizeof(recvBuf), 0);
            // if (count == 0)
            // {
            //     printf("服务端关闭，退出...\n");
            //     exit(1);
            // }
            // 处理返回来的数据
            handMkdirReturnData(socketFd);
        }
        else
        {
            printf("无效命令\n");
            continue;
        }
    }
    // 关闭套接字
    close(socketFd);
    return 0;
}
